package com.openapi.protocol.decode.subPackageHandle.hj212Stream;

import com.openapi.config.JT808ServerConfig;
import exsun.jt808.data.util.FtpUtils;
import exsun.jt808.data.util.executorsThread.FixedThreadHandleRunnable;
import exsun.jt808.data.upload_data.jsatl12.FileInfo;
import exsun.jt808.data.upload_data.jt808.FileBitStreamLoad;
import exsun.jt808.data.util.FileUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 文件数据缓存
 */
@Component
public class FileBitStreamCache {

    private static JT808ServerConfig jt808ServerConfig;
    @Autowired
    public void setJt808ServerConfig(JT808ServerConfig jt808ServerConfig) {
        FileBitStreamCache.jt808ServerConfig = jt808ServerConfig;
    }

    private static final Logger logger = LoggerFactory.getLogger(FileBitStreamCache.class);

    //key：文件名，value: 数据 (key:偏移量，数据)
    private static Map<String, Map<Integer, byte[]>> fileBitStreamCache = new HashMap<String, Map<Integer, byte[]>>();

    public static void AddFileBitStream(FileBitStreamLoad data){
        Map<Integer, byte[]> value = null;
        if(!fileBitStreamCache.containsKey(data.getFileName())){
            value = new HashMap<Integer, byte[]>();
        }else {
            value = fileBitStreamCache.get(data.getFileName());
        }
        value.put(data.getDataOffset(), data.getData());
        fileBitStreamCache.put(data.getFileName(), value);
    }

    public static boolean bReciveAll(String fileName){
        FileInfo fileInfo = FileInfoCache.getFileInfo(fileName);
        Map<Integer, byte[]> map = fileBitStreamCache.get(fileName);
        if(fileInfo==null|| map == null)return false;
        int len = 0;
        for ( byte[] data:  map.values()){
            len += data.length;
        }
//        logger.info("文件总量--" + fileInfo.getFileSize() + "--当前文件大小--" + len + "--文件名--" + fileName);
        if(fileInfo.getFileSize() == len){
            return true;
        }
        return false;
    }

    /**
     * 获取文件中缺失的项
     * @param fileName
     * @return null：无法获取文件信息(得不到数据长度)  其它：缺失项
     */
    public static Map<Integer, Integer> getMissItems(String fileName){
        Map<Integer, Integer> miss = new HashMap<Integer, Integer>();
        FileInfo fileInfo = FileInfoCache.getFileInfo(fileName);
        if(fileInfo == null){
            return miss;
        }
        //偏移量-长度

        if(!fileBitStreamCache.containsKey(fileName)){
            //miss.put(0, fileInfo.getFileSize());
            return miss;
        }

        Map<Integer, byte[]> datas = fileBitStreamCache.get(fileName);
        Object[] offsets = GetOffsets(fileName);

        for(int n = 0;n<offsets.length-1;n++){
            Integer offset = (Integer)offsets[n];
            Integer nextOffset = (Integer)offsets[n+1];
            if((offset + datas.get(offset).length != nextOffset)){
                miss.put(offset + datas.get(offset).length, nextOffset-offset-datas.get(offset).length);
            }
        }
        Integer lastOffset = (Integer)offsets[offsets.length-1];

        if(lastOffset + datas.get(lastOffset).length !=  fileInfo.getFileSize()){
            miss.put(lastOffset + datas.get(lastOffset).length, fileInfo.getFileSize()-lastOffset-datas.get(lastOffset).length);
        }
        int logoff = lastOffset + datas.get(lastOffset).length;
        logger.info("未接收完毕--偏移量" + logoff + "--文件名--" + fileName + "--文件总大小--" + fileInfo.getFileSize());
        return miss;
    }

    private static Object[] GetOffsets(String fileName){
        if(!fileBitStreamCache.containsKey(fileName))return new Object[0];
        Map<Integer, byte[]> datas = fileBitStreamCache.get(fileName);
        Object[] offsets = datas.keySet().toArray();
        Arrays.sort(offsets);
        return offsets;
    }

    public static byte[] getWholeStream(String fileName){
        try {

            FileInfo fileInfo = FileInfoCache.getFileInfo(fileName);
            if(fileInfo == null)return null;
            int size = fileInfo.getFileSize();
            byte[] data = new byte[size];
            Object[] offsets = GetOffsets(fileName);
            Map<Integer, byte[]> map = fileBitStreamCache.get(fileName);
            for(int n = 0;n<offsets.length;n++){
                int offset = (Integer) offsets[n];
                byte[] src = map.get(offset);
                System.arraycopy(src, 0, data, offset, src.length);
            }
            return data;
        }catch (Exception e){
            logger.error("getWholeStream error!!");
        }
        return null;
    }

    public static void removeStream(List<String> fileNames){
        for(String fileName: fileNames){
            removeStream(fileName);
        }
    }
    public static void removeStream(String fileName){
        if(fileBitStreamCache.containsKey(fileName)){
            fileBitStreamCache.remove(fileName);
        }
    }

    /**
     * 上传ftp
     * @param phoneNum
     * @param fileName
     * @return 返回null:未上传ftp（异常或文件不全）
     */
    public static String uploadfileFtp(String phoneNum, String fileName, byte[] stream){
        try {
            String filePath = "/AdasDms/"
                    + new SimpleDateFormat("yyyy-MM-dd").format(new Date())
                    + "/" + phoneNum;
//            boolean result = FixedThreadHandleRunnable.ftpSave(jt808ServerConfig.getJt808FtpServer(),
//                    jt808ServerConfig.getJt808FtpPort(), jt808ServerConfig.getJt808FtpUserName(),
//                    jt808ServerConfig.getJt808FtpPassword(), jt808ServerConfig.getJt808FtpBasePath(),
//                    filePath,fileName,stream,jt808ServerConfig.getJt808FtpTimeOut());
            FtpUtils.changeWorkingDirectory(jt808ServerConfig.getJt808FtpBasePath(),jt808ServerConfig.getAbsBasePath(),filePath,false);
            boolean result =FtpUtils.storageFile(fileName,stream,false);
            String path = "ftp://" + jt808ServerConfig.getJt808FtpServer() + ":" + jt808ServerConfig.getJt808FtpPort() +  filePath + "/" + fileName;
            logger.info("文件接收完毕,保存{},路径:{}",result?"成功":"失败", path);
            if(!result){
                FileUtil.writeAppendFile(path, stream);
                logger.info("保存到本地，{}",path);
            }
            return path;
        }catch (Exception e)
        {
            return null;
        }
    }

    public static int getFileSize(){
        return fileBitStreamCache.size();
    }

}
